# _*_ coding: UTF-8 _*_

import numpy as np
import matplotlib.pyplot as plt
from time import time

from scripts.optimizer.llso import LLSO
from scripts.optimizer.sdlso import SDLSO
from scripts.optimizer.ca_llso import CALLSO
from scripts.optimizer.basic_eas.particle_swarm_optimization import PSO

from scripts.optimizer.ca_sdlso import CASDLSO

from scripts.utils.tools import getDate, make_dir

from data.CEC.CEC2017.cec17_functions import cec17_test_func

plt.rc('font', family='Times New Roman')
np.set_printoptions(suppress=True, threshold=np.inf)


def cec(version=17, func_num=1):
    if version == 17:
        def cec17(x):
            f = [0]
            cec17_test_func(x=x, f=f, nx=len(x), mx=1, func_num=func_num)
            return f[0]

        return cec17
    else:
        print(f'version: {version} not exists.')
        quit(-1)


if __name__ == '__main__':
    date = getDate()
    make_dir(f'./results/{date}')

    # dimension = [10, 20, 30, 50, 100]
    d = 100
    bounds = (-100, 100)
    NP = 100

    for i in range(1, 31):
        if i == 2:
            continue

        func = cec(version=17, func_num=5)

        casdlso = CASDLSO(obj_func=func, dimension=d, bounds=bounds, NP=NP)
        casdlso.optimize(evaluations=1000)
        res = np.stack((casdlso.life.gBest, casdlso.acc, casdlso.loss), axis=1)
        np.savetxt(f'./results/{date}/casdlso_func{i}_d{d}.txt', res, fmt='%f')

        callso = CALLSO(obj_func=func, dimension=d, bounds=bounds, NP=NP, L=4, phi=0.4, Ns=4)
        callso.optimize(evaluations=1000)
        res = np.stack((callso.life.gBest, callso.acc), axis=1)
        np.savetxt(f'./results/{date}/callso_func{i}_d{d}.txt', res, fmt='%f')

        llso = LLSO(obj_func=func, dimension=d, bounds=bounds, NP=NP, L=4, phi=0.4)
        llso.optimize(evaluations=1000)
        np.savetxt(f'./results/{date}/llso_func{i}_d{d}.txt', llso.life.gBest)

        sdlso = SDLSO(obj_func=func, dimension=d, bounds=bounds, NP=NP)
        sdlso.optimize(evaluations=1000)
        np.savetxt(f'./results/{date}/sdlso_func{i}_d{d}.txt', sdlso.life.gBest)

        pso = PSO(obj_func=func, dimension=d, bounds=bounds, NP=NP, w=0.5, c1=2.0, c2=2.0)
        pso.optimize(evaluations=1000)
        np.savetxt(f'./results/{date}/pso_func{i}_d{d}.txt', pso.life.gBest)

        # abc = ABC(obj_func=func, dimension=d, bounds=bounds, NP=round(NP / 2), SL=100)
        # abc.optimize(evaluations=1000)

        plt.cla()
        plt.close('all')

        # plt.subplot(1, 2, 1)
        plt.plot(range(len(casdlso.life.gBest)), casdlso.life.gBest, label='CA-SDLSO')
        plt.plot(range(len(callso.life.gBest)), callso.life.gBest, label='CA-LLSO')
        plt.plot(range(len(sdlso.life.gBest)), sdlso.life.gBest, label='SDLSO')
        plt.plot(range(len(llso.life.gBest)), llso.life.gBest, label='LLSO')
        plt.plot(range(len(pso.life.gBest)), pso.life.gBest, label='PSO')

        plt.xlabel('FEs')
        plt.ylabel('Fitness')
        plt.title(f'CEC2017 func {i} d100')
        plt.legend()

        # plt.subplot(1, 2, 2)
        # plt.plot(range(len(callso.acc)), callso.acc, label='CA-LLSO acc', c='b')
        # plt.plot(range(len(casdlso.acc)), casdlso.acc, label='CA-SDLSO acc', c='r')
        # # plt.plot(range(len(casdlso.loss)), casdlso.loss, label='CA-SDLSO', c='r')
        # plt.xlabel('FEs')
        # plt.ylabel('Fitness')
        # plt.title(f'accuracy and loss')
        # plt.legend()

        plt.tight_layout()
        plt.savefig(rf'./results/{date}/CEC2017_func_{i}.png', dpi=600)

        print(f'CEC2017_func_{i}.png saved.')
